package network

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
	"strconv"
	"strings"
)

type DNSGreeter interface {
	DNS() DNSInterface
}

type DNSInterface interface {
	CreateRecord(args models.DNSRecordRequest) (result models.CreateResponseParams, err error)
	DeleteRecord(domain string, recordId uint64) (err error)
	ModifyRecord(domain string, recordId uint64, args models.DNSRecordRequest) (err error)
	DescribeRecord(domain string, recordId uint64) (result models.DNSRecordItem, err error)
	RecordListByType(domain string, recordType string) (list []models.DNSRecordItem, err error)
	RecordListAll(domain string) (list []models.DNSRecordItem, err error)
	DomainList() (list []models.DNSDomainItem, err error)
	DescribeDomain(name string) (result models.DNSDomainItem, err error)
}

type dns struct {
	network *Network
	client  *dnspod.Client
}

func newDNS(network *Network) DNSInterface {
	v := &dns{
		network: network,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(DnsEndPoint)
	client, _ := dnspod.NewClient(v.network.Credential(), "", cpf)
	v.client = client
	return v
}

// CreateRecord 增加DNS记录
func (d *dns) CreateRecord(args models.DNSRecordRequest) (result models.CreateResponseParams, err error) {
	request := dnspod.NewCreateRecordRequest()
	request.Domain = common.StringPtr(args.Domain)
	request.RecordType = common.StringPtr(args.RecordType)
	request.RecordLine = common.StringPtr("默认")
	request.Value = common.StringPtr(args.Value)
	if args.TTL < 60 || args.TTL > 3600 {
		request.TTL = common.Uint64Ptr(600)
	} else {
		request.TTL = common.Uint64Ptr(args.TTL)
	}
	if args.RecordType == "MX" && args.MX > 0 {
		request.MX = common.Uint64Ptr(args.MX)
	}
	request.Status = common.StringPtr("ENABLE")
	request.Remark = common.StringPtr(args.Remark)
	response, err := d.client.CreateRecord(request)
	if err != nil {
		return
	}
	res := response.Response
	result.RequestId = *res.RequestId
	result.InstanceSet = append(result.InstanceSet, strconv.FormatUint(*res.RecordId, 10))
	return
}

func (d *dns) DeleteRecord(domain string, recordId uint64) (err error) {
	request := dnspod.NewDeleteRecordRequest()
	request.Domain = common.StringPtr(domain)
	request.RecordId = common.Uint64Ptr(recordId)
	_, err = d.client.DeleteRecord(request)
	return
}
func (d *dns) ModifyRecord(domain string, recordId uint64, args models.DNSRecordRequest) (err error) {
	request := dnspod.NewModifyRecordRequest()
	request.Domain = common.StringPtr(domain)
	request.RecordId = common.Uint64Ptr(recordId)
	if d.checkNotEmpty(args.RecordType) {
		request.RecordType = common.StringPtr(args.RecordType)
	}
	if d.checkNotEmpty(args.Value) {
		request.Value = common.StringPtr(args.Value)
	}
	if d.checkNotZero(strconv.FormatUint(args.MX, 10)) && args.RecordType == "MX" {
		request.MX = common.Uint64Ptr(args.MX)
	}
	if d.checkNotZero(strconv.FormatUint(args.TTL, 10)) {
		request.TTL = common.Uint64Ptr(args.TTL)
	}
	request.Status = common.StringPtr("Enable")
	_, err = d.client.ModifyRecord(request)
	return
}

func (d *dns) DescribeRecord(domain string, recordId uint64) (result models.DNSRecordItem, err error) {
	request := dnspod.NewDescribeRecordRequest()
	request.Domain = common.StringPtr(domain)
	request.RecordId = common.Uint64Ptr(recordId)
	response, err := d.client.DescribeRecord(request)
	if err != nil {
		return
	}
	res := response.Response.RecordInfo
	record := models.DNSRecordItem{
		RecordId:      *res.Id,
		Value:         *res.Value,
		Status:        strconv.FormatUint(*res.Enabled, 10),
		UpdatedOn:     *res.UpdatedOn,
		Line:          *res.RecordLine,
		LineId:        *res.RecordLineId,
		Type:          *res.RecordType,
		MonitorStatus: *res.MonitorStatus,
		Remark:        *res.Remark,
		TTL:           *res.TTL,
		MX:            *res.MX,
	}
	return record, nil
}

func (d *dns) RecordListByType(domain string, recordType string) (list []models.DNSRecordItem, err error) {
	return d.queryRecord(domain, recordType)
}

// RecordListAll 获取域名的记录列表
func (d *dns) RecordListAll(domain string) (list []models.DNSRecordItem, err error) {
	return d.queryRecord(domain, "")
}

func (d *dns) queryRecord(domain string, recordType string) (list []models.DNSRecordItem, err error) {
	request := dnspod.NewDescribeRecordListRequest()
	request.Domain = common.StringPtr(domain)
	if strings.TrimSpace(recordType) != "" {
		request.RecordType = common.StringPtr(recordType)
	}
	request.Offset = common.Uint64Ptr(0)
	request.Limit = common.Uint64Ptr(3000)
	response, err := d.client.DescribeRecordList(request)
	if err != nil {
		return
	}
	for _, row := range response.Response.RecordList {
		list = append(list, models.DNSRecordItem{
			RecordId:      *row.RecordId,
			Value:         *row.Value,
			Status:        *row.Status,
			UpdatedOn:     *row.UpdatedOn,
			Name:          *row.Name,
			Line:          *row.Line,
			LineId:        *row.LineId,
			Type:          *row.Type,
			MonitorStatus: *row.MonitorStatus,
			Remark:        *row.Remark,
			TTL:           *row.TTL,
			MX:            *row.MX,
		})
	}
	return
}

func (d *dns) checkNotEmpty(str string) bool {
	if strings.TrimSpace(str) != "" {
		return true
	}
	return false
}

func (d *dns) checkNotZero(number string) bool {
	n, err := strconv.Atoi(number)
	if err == nil && n > 0 {
		return true
	}
	return false
}

func (d *dns) DomainList() (list []models.DNSDomainItem, err error) {
	request := dnspod.NewDescribeDomainListRequest()
	request.Offset = common.Int64Ptr(0)
	request.Limit = common.Int64Ptr(3000)
	response, err := d.client.DescribeDomainList(request)
	if err != nil {
		return
	}
	for _, row := range response.Response.DomainList {
		list = append(list, models.DNSDomainItem{
			DomainId:         *row.DomainId,
			Name:             *row.Name,
			Status:           *row.Status,
			TTL:              *row.TTL,
			CNAMESpeedup:     *row.CNAMESpeedup,
			DNSStatus:        *row.DNSStatus,
			Grade:            *row.Grade,
			GroupId:          *row.GroupId,
			SearchEnginePush: *row.SearchEnginePush,
			Remark:           *row.Remark,
			RecordCount:      *row.RecordCount,
			CreatedOn:        *row.CreatedOn,
			UpdatedOn:        *row.UpdatedOn,
			Owner:            *row.Owner,
		})
	}
	return
}

func (d *dns) DescribeDomain(name string) (result models.DNSDomainItem, err error) {
	request := dnspod.NewDescribeDomainRequest()
	request.Domain = common.StringPtr(name)
	response, err := d.client.DescribeDomain(request)
	if err != nil {
		return
	}
	res := response.Response.DomainInfo
	domain := models.DNSDomainItem{
		DomainId:         *res.DomainId,
		Name:             *res.Domain,
		Status:           *res.Status,
		TTL:              *res.TTL,
		CNAMESpeedup:     *res.CnameSpeedup,
		DNSStatus:        *res.DnsStatus,
		Grade:            *res.Grade,
		GroupId:          *res.GroupId,
		SearchEnginePush: *res.SearchEnginePush,
		Remark:           *res.Remark,
		RecordCount:      *res.RecordCount,
		CreatedOn:        *res.CreatedOn,
		UpdatedOn:        *res.UpdatedOn,
		Owner:            *res.Owner,
	}
	return domain, nil
}
